/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;


import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.isfd.constant.enums.IsfdLoadExperimentParameterEnum;
import com.comac.ins.isfd.domain.metadata.MetaData;
import com.comac.ins.isfd.domain.vo.GridFsTreeNodeVo;
import com.comac.ins.isfd.service.IGridFsService;
import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;
import lombok.extern.slf4j.Slf4j;
import org.bson.BsonValue;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@Service
public class GridFsServiceImpl implements IGridFsService {

    @Autowired
    private GridFsTemplate gridFsTemplate;

    private final ExecutorService executor = Executors.newFixedThreadPool(20);

    /**
     * 上传文件到GridFS
     */
    public List<String> uploadFile(MultipartFile[] files, String versionId, String taskId, String type) throws IOException, ExecutionException, InterruptedException {
        List<CompletableFuture<String>> futures = new ArrayList<>();
        if (type.equals("uploadCustomizationFile")) {
            deleteExistingFiles("", taskId, versionId, type);
        }
        for (MultipartFile file : files) {
            futures.add(CompletableFuture.supplyAsync(() -> {
                try {
                    if (!type.equals("uploadCustomizationFile")) {
                        deleteExistingFiles(file.getOriginalFilename(), taskId, versionId, "");
                        MetaData metaData = new MetaData();
                        metaData.setVersionId(versionId);
                        metaData.setTaskId(taskId);
                        metaData.setType(type);
                        String chineseName = IsfdLoadExperimentParameterEnum.valueOf(type.toUpperCase()).getChineseName();
                        if (chineseName.equalsIgnoreCase(IsfdLoadExperimentParameterEnum.NODE_INFO.getChineseName())) {
                            StringBuffer name = new StringBuffer();
                            name.append(chineseName);
                            String fileName = file.getOriginalFilename();
                            if (fileName.contains("/")) {
                                String[] parts = fileName.split("/");
                                fileName = parts[parts.length - 1];
                            }
                            if (IsfdLoadExperimentParameterEnum.NODE_INFO_JS.getFileList().contains(fileName.toUpperCase())) {
                                name.append(File.separator + IsfdLoadExperimentParameterEnum.NODE_INFO_JS.getChineseName());
                            } else if (IsfdLoadExperimentParameterEnum.NODE_INFO_JY.getFileList().contains(fileName.toUpperCase())) {
                                name.append(File.separator + IsfdLoadExperimentParameterEnum.NODE_INFO_JY.getChineseName());
                            } else if (IsfdLoadExperimentParameterEnum.NODE_INFO_CW.getFileList().contains(fileName.toUpperCase())) {
                                name.append(File.separator + IsfdLoadExperimentParameterEnum.NODE_INFO_CW.getChineseName());
                            } else if (IsfdLoadExperimentParameterEnum.NODE_INFO_PW.getFileList().contains(fileName.toUpperCase())) {
                                name.append(File.separator + IsfdLoadExperimentParameterEnum.NODE_INFO_PW.getChineseName());
                            }
                            metaData.setFolder(String.valueOf(name));
                        } else if (chineseName.equalsIgnoreCase(IsfdLoadExperimentParameterEnum.CUMULATIVE_RESULT_1G.getChineseName()) ||
                            chineseName.equalsIgnoreCase(IsfdLoadExperimentParameterEnum.CUMULATIVE_RESULT_1G_DYNAMIC.getChineseName())) {
                            StringBuffer name = new StringBuffer();
                            name.append(chineseName);
                            String fileName = file.getOriginalFilename();
                            if (fileName.contains("ADD_FORCE_GZ")) {
                                name.append(File.separator + "需要提取的载荷");
                            }
                            metaData.setFolder(String.valueOf(name));
                        } else {
                            metaData.setFolder(chineseName);
                        }
                        String fileName = file.getOriginalFilename();
                        if (fileName.contains("/")) {
                            String[] parts = fileName.split("/");
                            fileName = parts[parts.length - 1];
                        }
                        return gridFsTemplate.store(
                            file.getInputStream(),
                            fileName,
                            file.getContentType(),
                            metaData
                        ).toString();
                    } else {
                        MetaData metaData = new MetaData();
                        metaData.setVersionId(versionId);
                        metaData.setTaskId(taskId);
                        metaData.setType(type);
                        String originalFilename = file.getOriginalFilename();
                        if (originalFilename != null) {
                            int lastIndex = originalFilename.lastIndexOf("/");
                            String path;
                            String fileName;
                            if (lastIndex != -1) {
                                path = originalFilename.substring(0, lastIndex);
                                fileName = originalFilename.substring(lastIndex + 1);
                            } else {
                                path = "";
                                fileName = originalFilename;
                            }
                            metaData.setFolder(path);
                            // 创建上传路径中的各级文件夹（如果不存在）
                            return gridFsTemplate.store(
                                file.getInputStream(),
                                fileName,
                                file.getContentType(),
                                metaData
                            ).toString();
                        }
                    }
                } catch (IOException e) {
                    throw new RuntimeException("文件上传失败： " + file.getOriginalFilename());
                }
                return null;
            }, executor));

        }
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
            futures.toArray(new CompletableFuture[0])
        );
        CompletableFuture<List<String>> allRusults = allFutures.thenApply(v ->
            futures.stream()
                .map(CompletableFuture::join)
                .toList()
        );
        return allRusults.get();
    }

    /**
     * 根据ID下载文件
     */
    public GridFsResource downloadFileById(String fileId) {
        GridFSFile gridFSFile = gridFsTemplate.findOne(
            Query.query(Criteria.where("_id").is(fileId))
        );

        if (gridFSFile == null) {
            return null;
        }

        return gridFsTemplate.getResource(gridFSFile);
    }

    /**
     * 根据文件名下载文件
     */
    public GridFsResource downloadFileByName(String fileName, String versionId, String taskId) {
        GridFSFile gridFSFile = gridFsTemplate.findOne(
            Query.query(Criteria.where("filename").is(fileName)
                .and("metadata.taskId").is(taskId))
        );

        if (gridFSFile == null) {
            return null;
        }
        return gridFsTemplate.getResource(gridFSFile);
    }

    /**
     * 获取文件列表
     */
    public GridFSFindIterable listFiles(String taskId) {
        return gridFsTemplate.find(new Query(Criteria.where("metadata.taskId").is(taskId)));
    }

    /**
     * 删除文件
     */
    public void deleteFile(String fileId) {
        gridFsTemplate.delete(Query.query(Criteria.where("_id").is(fileId)));
    }

    /**
     * 复制文件
     */
    @Override
    public void copyFiles(String oldVersionId, String newVersionId) {
        Query query = Query.query(Criteria.where("metadata.versionId").is(oldVersionId)
            .and("metadata.taskId").exists(false));
        //先判断新版本是否已存在
        GridFSFile existingFile = gridFsTemplate.findOne(Query.query(Criteria.where("metadata.versionId").is(newVersionId)
            .and("metadata.taskId").exists(false)));
        if (existingFile != null) {
            return;
        }
        gridFsTemplate.find(query).forEach(gridFSFile -> {
            try {
                //获取文件ID和元数据
//                BsonValue id = gridFSFile.getId();
                Document metadata = gridFSFile.getMetadata();
                //创建新的元数据
                Document newMetaData = new Document(metadata);
                newMetaData.put("versionId", newVersionId);
                //获取文件内容
                GridFsResource resource = gridFsTemplate.getResource(gridFSFile);
                InputStream content = resource.getInputStream();
                String fileName = resource.getFilename();
                //保存
                gridFsTemplate.store(content, fileName, newMetaData);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

    }

    /**
     * 批量删除
     */
    @Override
    public void deleteFiles(String taskId) {
        Query query = Query.query(Criteria.where("metadata.taskId").is(taskId)
            .and("metadata.type").is("output"));
        gridFsTemplate.delete(query);
    }

    @Override
    public GridFsTreeNodeVo buildFolderTreeByVersionId(String taskId, String fileName) {
        // 创建根节点
        int i = 0;
        GridFsTreeNodeVo root = new GridFsTreeNodeVo();
        root.setFileName("/");
        root.setSize(0.0);
        root.setId(String.valueOf(i));
        root.setDirectory(true);
        // 查询指定 versionId 的所有文件
        Criteria criteria = new Criteria();
        criteria.and("metadata.taskId").is(taskId);
        if (StringUtils.isNotBlank(fileName)) {
            String regexFileName = ".*" + fileName + ".*";
            criteria.and("filename").regex(regexFileName, "i");
        }
        Query query = Query.query(criteria);
        GridFSFindIterable gridFSFiles = gridFsTemplate.find(query);
         List<Document> files = new ArrayList<>();
        for (GridFSFile gridFsFile : gridFSFiles) {
            Document metadata = gridFsFile.getMetadata();
            Document fileDoc = new Document();
            fileDoc.put("filename", gridFsFile.getFilename());
            long sizeByte = gridFsFile.getLength();
            double sizeMB = (double) sizeByte / (1024);
            fileDoc.put("size", sizeMB);
            fileDoc.put("folder", metadata != null ? metadata.getString("folder") : "");
            fileDoc.put("id", gridFsFile.getId());
            fileDoc.put("date", gridFsFile.getUploadDate());
            files.add(fileDoc);
        }
        if (files.isEmpty()) {
            return root;
        }
        // 构建文件树
        for (Document file : files) {
            String filename = file.getString("filename");
            double size = file.getDouble("size");
            String folderPath = file.getString("folder");
            BsonValue bsonId = (BsonValue) file.get("id");
            String id = bsonId.asObjectId().getValue().toString();
            Date date = file.getDate("date");
            // 如果没有文件夹路径，直接添加到根节点
            if (folderPath == null || folderPath.isEmpty()) {
                GridFsTreeNodeVo GridFsTreeNodeVo = new GridFsTreeNodeVo();
                GridFsTreeNodeVo.setFileName(filename);
                GridFsTreeNodeVo.setSize(size);
                GridFsTreeNodeVo.setId(id);
                GridFsTreeNodeVo.setFolder(folderPath);
                GridFsTreeNodeVo.setDirectory(false);
                GridFsTreeNodeVo.setDate(date);
                root.getChildren().add(GridFsTreeNodeVo);
                continue;
            }

            // 分割文件夹路径
            String separator = File.separator;
            String[] pathParts = folderPath.split(separator.equals("\\") ? "\\\\" : separator);
            GridFsTreeNodeVo currentNode = root;

            // 遍历文件夹路径，创建中间目录节点
            for (String part : pathParts) {
                if (part.isEmpty()) continue; // 跳过空路径部分
                // 查找或创建子目录节点
                i++;
                GridFsTreeNodeVo childNode = findOrCreateChild(currentNode, part, String.valueOf(i), date, true);
                currentNode = childNode;
            }

            // 添加文件节点到最终目录
            GridFsTreeNodeVo GridFsTreeNodeVo = new GridFsTreeNodeVo();
            GridFsTreeNodeVo.setFileName(filename);
            GridFsTreeNodeVo.setSize(size);
            GridFsTreeNodeVo.setDirectory(false);
            GridFsTreeNodeVo.setId(id);
            GridFsTreeNodeVo.setFolder(folderPath);
            GridFsTreeNodeVo.setDate(date);
            currentNode.getChildren().add(GridFsTreeNodeVo);
        }
        // 计算目录大小
        calculateDirectorySizes(root);
        return root;
    }

    /**
     * 在父节点中查找子节点，如果不存在则创建
     */
    private GridFsTreeNodeVo findOrCreateChild(GridFsTreeNodeVo parent, String name, String id, Date date, boolean isDirectory) {
        for (GridFsTreeNodeVo child : parent.getChildren()) {
            if (child.getFileName().equals(name)) {
                return child;
            }
        }

        // 子节点不存在，创建新节点
        GridFsTreeNodeVo newNode = new GridFsTreeNodeVo();
        newNode.setFileName(name);
        newNode.setFolder(name);
        newNode.setSize(0.0);
        newNode.setId(String.valueOf(id));
        newNode.setDirectory(isDirectory);
        newNode.setDate(date);
        parent.getChildren().add(newNode);
        return newNode;
    }

    /**
     * 递归计算目录大小
     */
    private double calculateDirectorySizes(GridFsTreeNodeVo node) {
        if (!node.isDirectory()) {
            return node.getSize();
        }

        double totalSize = 0;
        for (GridFsTreeNodeVo child : node.getChildren()) {
            totalSize += calculateDirectorySizes(child);
        }

        node.setSize(totalSize);
        return totalSize;
    }

    public void deleteExistingFiles(String filename, String taskId, String versionId, String type) {
        Criteria criteria = new Criteria();
        if (filename != null && !filename.isEmpty()) {
            criteria.and("filename").is(filename);
        }
        if (taskId != null && !taskId.isEmpty()) {
            criteria.and("metadata.taskId").is(taskId);
        }
        if (versionId != null && !versionId.isEmpty()) {
            criteria.and("metadata.versionId").is(versionId);
        }
        if (type != null && !type.isEmpty()) {
            criteria.and("metadata.type").is(type);
        }
        Query query = Query.query(criteria);
        gridFsTemplate.delete(query);
    }

}
